package com.longtop.framework.orm;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ibatis.sqlmap.engine.execution.SqlExecutor;
import com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback;
import com.ibatis.sqlmap.engine.scope.StatementScope;

/**
 * 覆写 Ibatis 源码，拦截 sql查询 的操作，解决多数据库分页问题
 * 
 * @author 胡砥峰
 */
public class IBatisSqlExecutor extends SqlExecutor {
	private static final Log logger = LogFactory.getLog(IBatisSqlExecutor.class);
	private IDialect dialect;
	private boolean enableCustomizedPaged = false;
	private int count; // 总记录数
	private boolean needCount = false;// 判断是否需要自动计算COUNT数

	public void executeQuery(StatementScope request, Connection conn, String sql, Object[] parameters, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException {
		// 是否需要自动计算COUNT：
		if (needCount) {
			// 原sql应该是没有任何分页内容的，例如：select * from T_SYS_USER
			String countSQL = IBatisUtils.getCountSQL(sql);// 根据原SQL拼装成CountSQL

			PreparedStatement prestmt = null;
			ResultSet rs = null;
			try {
				prestmt = conn.prepareStatement(countSQL);
				if (parameters.length != 0) {// 设置参数
					for (int i = 0; i < parameters.length; i++) {
						if (parameters[i] != null) {
							prestmt.setObject(i + 1, parameters[i]);
						}
					}
				}
				rs = prestmt.executeQuery();
				if (rs.next()) {
					this.count = rs.getInt(1);// 取得 总记录数
				}
			} catch (SQLException e) {
				e.printStackTrace();
				logger.error("执行Count时发生了异常. SQL = [" + countSQL + "], 原SQL=[" + sql + "]", e);
			} finally {
				if (rs != null) {
					try {
						rs.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				if (prestmt != null) {
					try {
						prestmt.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
			this.needCount = false;
		}

		// 判断是否需要分页/ 备注：DB2下的dialect组装分页语句 测试发现效率有问题。
		if ((((skipResults != 0) || (maxResults != -999999))) && (supportsPaged())) {

			sql = this.dialect.getPagedString(sql, skipResults, maxResults);// 使用dialect分页！

			if (logger.isDebugEnabled()) {
				logger.debug(sql);
			}

			// 每次执行分页查询后， 重置某些参数
			skipResults = 0;
			maxResults = -999999;
			this.enableCustomizedPaged = false;
		}
		System.out.println();
		System.out.println("SQL>>:" + sql);
		super.executeQuery(request, conn, sql, parameters, skipResults, maxResults, callback);
	}

	public IBatisSqlExecutor() {

	}

	public IDialect getDialect() {
		return this.dialect;
	}

	public void setDialect(IDialect dialect) {
		this.dialect = dialect;
	}

	public boolean isEnableCustomizedPaged() {
		return this.enableCustomizedPaged;
	}

	public void setEnableCustomizedPaged(boolean enableCustomizedPaged) {
		this.enableCustomizedPaged = enableCustomizedPaged;
	}

	/**
	 * 是否支持分页
	 * 
	 * @return
	 */
	public boolean supportsPaged() {
		if ((this.enableCustomizedPaged) && (this.dialect != null)) {
			return this.dialect.supportsPaged();
		}
		return false;
	}

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public boolean isNeedCount() {
		return needCount;
	}

	public void setNeedCount(boolean needCount) {
		this.needCount = needCount;
	}

}
